home *** CD-ROM | disk | FTP | other *** search
- /*
- SpinLib.c
-
- Code for spinning a beachball cursor.
- */
-
- #include "SpinLibInterns.h"
-
- #include <Traps.h>
- #include <GestaltEqu.h>
- #include <Think.h>
-
- #ifndef CrsrBusy
- #define CrsrBusy 0x8CD /*[GLOBAL VAR] Cursor locked out? [byte]*/
- #endif
-
-
- pascal long __GetVBLRec (void);
- pascal long __GetVBLRec (void)
- = 0x2E88;
-
- CursorTask gCursTask; /* Global structure */
- Boolean gCursInstalled = false; /* installation global */
- Boolean gCursInited=false;
-
- /*
- SpinInit
-
- Loads the cursors and sets up the spinning stuff...
- */
- OSErr SpinInit(void){
- Handle h;
- short i;
- OSErr err;
-
- if (gCursInited)
- return noErr;
-
- gCursInstalled = false; /* we are not installed yet */
- gCursInited=false;
-
- /* allocate cursor memory */
- gCursTask.cursors=(CursHandle *)NewPtr (8*sizeof (CursHandle));
-
- gCursTask.value=0;
-
- for (i=0; i < 8; i++) { /* cycle through the rest */
-
- h = (Handle)GetCursor (128+i); /* black and white */
-
- if (h == nil) /* did we get the cursor */
- return ResError(); /* if no, return error */
-
- DetachResource(h);
- HNoPurge (h); /* force it unpurgeable */
- HLockHi (h); /* and lock it high */
-
- gCursTask.cursors[i]=(CursHandle)h;
- }
-
- gCursInited=true;
-
- return noErr;
- }
-
- /*
- SpinStart
-
- Starts the spinning of the beachball.
- */
- OSErr SpinStart(short direction){
- OSErr err; /* returnable error */
- short i; /* dummy counter */
- Handle h;
-
- if (!gCursInited)
- return paramErr;
-
- if (gCursInstalled) /* if we are already installed, */
- return noErr; // do nothing...
-
- if (direction==0)
- direction=1;
-
- if (direction>1)
- direction=1;
- if (direction<-1)
- direction=-1;
-
- gCursTask.direction=direction;
-
- gCursTask.vblTask.qType = vType; /* set up the VBL task record */
- gCursTask.vblTask.vblAddr = (ProcPtr)SpinTask;
- gCursTask.vblTask.vblCount = 20;
- gCursTask.vblTask.vblPhase = 0;
- gCursTask.vblA5 = SetCurrentA5();
-
- err = VInstall ((QElemPtr)&gCursTask.vblTask); /* install the VBL task */
-
- if (err)
- return err; /* if errors, return them, else */
- else {
- gCursInstalled = true; /* declare the task installed */
- return noErr; /* and return no error */
- }
- }
-
- /*
- SpinTask
-
- This is the meat and bones of the spinning cursor calls. When the VBL task count (vblCount) goes to zero, the
- Vertical Retrace Manager will call SpinCursor(). Our job will be to set the cursor to the current frame, and then
- to advance the frame. The thing to remember is that we are executed during interrupt, and we are not allowed to
- use Memory Manager calls... as well as a billion other things.
-
- Another cool thing to note is that at the time of our interrupt, a pointer to the installed VBL task will be
- placed in A0. Since we installed with some more globals attached, these will also be available to us; kind of
- a sneaky way around the messed up A5 problem.
-
- Also remember that the vblCount is zero at this time. If we leave this function without returning a nonzero value,
- the task will never return to SpinCursor again. So, we articulately return the vblCount to frequency, which is
- why the task happens so regulary...
- */
- pascal void SpinTask(void){
- CursorTaskPtr taskPtr;
- Boolean busy;
- CursPtr cp;
-
- taskPtr=(CursorTaskPtr)__GetVBLRec();
-
- busy = (*(Boolean *)CrsrBusy); /* determine the cursor state */
-
- if (!busy) { /* if it is available to us */
- /* set the cursor and frame advance */
- cp=(CursPtr)(*(taskPtr->cursors[taskPtr->value]));
-
- SetCursor(cp);
-
- taskPtr->value += taskPtr->direction;
-
- if (taskPtr->value>7)
- taskPtr->value=0;
-
- if (taskPtr->value<0)
- taskPtr->value=7;
- }
-
- taskPtr->vblTask.vblCount = 3; /* restore the VBL task */
- }
-
- /*
- SpinStop
-
- Stops the spinning of the cursor.
- */
- OSErr SpinStop(void){
- OSErr err;
- short i;
-
- if (!gCursInstalled) /* if we were not installed, */
- return noErr; /* alert them and exit */
-
- err = VRemove ((QElemPtr)&gCursTask.vblTask); /* remove the VBL task */
- gCursInstalled=false;
-
- SetCursor (&arrow); /* restore the cursor to an arrow */
-
- return err;
- }
-
- /*
- SpinSpinning
-
- returns state of the cursor.
- */
- Boolean SpinSpinning(void){
- return gCursInstalled;
- }
-
- /*
- SpinCleanup
-
- Dispose of the memory being used by the spinning cursors...
- */
- OSErr SpinCleanup(void){
- short i;
- OSErr err;
-
- if (gCursInstalled)
- SpinStop();
-
- if (!gCursInited)
- return noErr;
-
- for (i=0;i<8;i++){
- HUnlock((Handle)(gCursTask.cursors[i]));
- HPurge((Handle)(gCursTask.cursors[i]));
- DisposeHandle((Handle)gCursTask.cursors[i]);
- }
-
- DisposePtr((Ptr)(gCursTask.cursors));
-
- return noErr; /* and return no error */
- }
-